package com.m1905.lib.download;

import android.os.Looper;
import android.text.TextUtils;

import com.m1905.lib.download.db.DBManager;
import com.m1905.lib.download.listener.DatabaseUpdateCallBack;
import com.m1905.lib.download.listener.DispatchDownloadStatusListener;
import com.m1905.lib.download.listener.DownloadStatusListener;
import com.m1905.lib.download.model.DataWrapper;
import com.m1905.lib.download.model.DownloadDBItem;
import com.m1905.lib.download.model.State;
import com.m1905.lib.download.task.DownloadTask;
import com.m1905.lib.download.util.DLog;
import com.m1905.lib.download.util.DownloadPreferences;
import com.m1905.lib.download.util.Utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author wanghao
 * @date 2023/11/17.
 * @des
 */
public class DownloadController {

    private final CopyOnWriteArrayList<DownloadDBItem> downloadList;
    private DispatchDownloadStatusListener unionDownloadStatusListener;

    public DownloadController(DispatchDownloadStatusListener listener) {
        unionDownloadStatusListener = listener;
        downloadList = new CopyOnWriteArrayList<>(DBManager.queryAll());
        for (DownloadDBItem item : downloadList) {
            if (item.getState() < State.FAILURE) {
                item.setState(State.CANCELLED);
            }
        }
    }

    public List<DownloadDBItem> getDownloadList() {
        return downloadList;
    }

    public void startDownloadList(DataWrapper wrapper) {
        List<DownloadDBItem> ls = wrapper.getData();
        for (int i = 0; i < ls.size(); i++) {
            startDownload(ls.get(i));
        }
        unionDownloadStatusListener.dispatchComplete(wrapper);
    }

    public void insertList(DataWrapper wrapper) {
        List<DownloadDBItem> ls = wrapper.getData();
        if (DBManager.insertToDatabase(ls)) {
            downloadList.addAll(ls);
        }
        unionDownloadStatusListener.dispatchComplete(wrapper);
    }

    public void stopDownloadList(DataWrapper wrapper) {
        List<DownloadDBItem> ls = wrapper.getData();
        for (int i = 0; i < ls.size(); i++) {
            stopDownload(ls.get(i));
        }
        unionDownloadStatusListener.dispatchComplete(wrapper);
    }

    public void deleteDownloadList(DataWrapper wrapper) {
        List<DownloadDBItem> ls = wrapper.getData();
        for (int i = 0; i < ls.size(); i++) {
            deleteDownload(ls.get(i));
        }
        unionDownloadStatusListener.dispatchComplete(wrapper);
    }

    public List<DownloadDBItem> query(int types, int states, String contentId, String episodeId, int limit) {
        List<DownloadDBItem> result = new ArrayList<>();
        if (downloadList != null && downloadList.size() > 0) {
            for (int i = 0; i < downloadList.size(); i++) {
                DownloadDBItem item = downloadList.get(i);
                if (Utils.queryEquals(types, item.getType())
                        && Utils.queryEquals(states, item.getState())
                        && Utils.queryEquals(contentId, item.getContentId())
                        && Utils.queryEquals(episodeId, item.getEpisodeId())) {
                    result.add(item);
                    if (result.size() >= limit) {
                        break;
                    }
                }
            }
        }
        return result;
    }


    private void startDownload(DownloadDBItem item) {
        if (item != null) {
            DownloadDBItem targetItem = Utils.findDownloadItemFromDownloadList(downloadList, item);
            DLog.e("DownloadController startDownload target: " + targetItem);
            if (targetItem != null) {
                if (targetItem.getState() < State.FAILURE || targetItem.getState() == State.SUCCESS || targetItem.getState() == State.DELETE) {
                    DLog.e("DownloadController download is running  success or delete give up, current state is: " + targetItem.getState());
                    return;
                }
                targetItem.setResume(item.isResume());
                targetItem.setState(State.WAITING);
                boolean needInsert = targetItem.getId() <= 0;
                targetItem.setTask(new DownloadTask(Looper.myLooper(), new DatabaseUpdateCallBack(targetItem, unionDownloadStatusListener)));
                if (targetItem.getTask().preWaiting(targetItem)) {
                    targetItem.getTask().waiting(needInsert);
                    targetItem.getTask().executeOnExecutor(targetItem);
                }
            } else {
                item.setState(State.WAITING);
                if (TextUtils.isEmpty(item.getPath())) {
                    item.setPath(DownloadPreferences.getGeneratePathListener().onGenerateFilePath(DownloadPreferences.getAppContext(), item));
                } else {
                    // 如果支持断点续传，需要判断文件是否存在，如果存在就删除原文件再下载, 防止本地有同名文件导致下载失败。
                    if (item.isResume()) {
                        File file = new File(item.getPath());
                        if (file.exists()) {
                            file.delete();
                        }
                    }
                }
                item.setTask(new DownloadTask(Looper.myLooper(), new DatabaseUpdateCallBack(item, unionDownloadStatusListener)));
                boolean needInsert = item.getId() <= 0;
                if (item.getTask().preWaiting(item)) {
                    downloadList.add(item);
                    DLog.e("downloadList.addItem " + downloadList.size() + "  add success:" + item);
                    item.getTask().waiting(needInsert);
                    item.getTask().executeOnExecutor(item);
                }
            }
        }
    }


    private void stopDownload(DownloadDBItem item) {
        if (item != null) {
            DownloadDBItem targetItem = Utils.findDownloadItemFromDownloadList(downloadList, item);
            if (targetItem != null && targetItem.getTask() != null) {
                DLog.e("DownloadController stopDownload: " + targetItem);
                if (targetItem.getTask() == null) {
                    targetItem.setTask(new DownloadTask(Looper.myLooper(), new DatabaseUpdateCallBack(targetItem, unionDownloadStatusListener)));
                }
                targetItem.getTask().cancel();
            }
        }
    }


    private void deleteDownload(DownloadDBItem item) {
        if (item != null) {
            int index = Utils.findDownloadItemFromDownloadListPosition(downloadList, item);
            DLog.e("DownloadController deleteDownload: " + index);
            if (index != -1) {
                DownloadDBItem target = downloadList.get(index);
                downloadList.remove(index);
                File file = new File(target.getPath());
                if (file.exists()) {
                    file.delete();
                }
                if (target.getTask() == null) {
                    target.setTask(new DownloadTask(Looper.myLooper(), new DatabaseUpdateCallBack(target, unionDownloadStatusListener)));
                }
                target.getTask().delete();
            }
        }
    }
}
